﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using DatabaseAdminTools.MiniForms;
using DatabaseAdminTools.OptionForms;
using DatabaseAdminTools.Connections;

namespace DatabaseAdminTools
{
    public partial class Form1 : Form
    {
        #region Variables definition
        private static List<Connection> ConnectionList; // mang cac Connection

        private List<bool> connectionOpened; // mang chua thong tin ve cac Connection / Conn nao dc open // chua open

        private List<List<bool>> databaseOpened; // mang chua thong tin ve cac database da dc open / chua open

        private int selectedConnection = -1; // chi so Connection hien tai dang duoc chon

        private Point databaseSelected = new Point (-1, -1);

        private TableForm tableView = null;

        private bool[] optionSelected = new bool[] { false, false, false, false, false };

        private int selectedOptionIndex
        {
            get
            {
                for (int i = 0; i < 5; i++)
                {
                    if (optionSelected[i])
                        return i;
                }
                return -1;
            }
        }
        #endregion

        #region Constructors and load event
        public Form1()
        {
            InitializeComponent();
            this.Size = new Size(1000, 600);
            ConnectionList = new List<Connection>();
            connectionOpened = new List<bool>();
            databaseOpened = new List<List<bool>>();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            openConnectionFiles();
            reverseTableInfoVisible(); // -> visible to false
            ToolTip toolTip = new ToolTip();
            toolTip.SetToolTip(showHideTreeviewButton, "Click to Show / Hide Connection tree view");
            toolTip.SetToolTip(showHideTableInfoButton, "Click to Show / Hide Table Information Tab");
            toolTip.SetToolTip(showHideToolBarButton, "Click to Show / Hide Toolbars");
        }
        #endregion

        #region Connection - Tree view - Data

        #region Connection
        //show a Connection property form, and when user click ok, add new Connection to tree view
        private void showConnectionForm(bool newConnection)
        {
            TreeNode node = treeView.SelectedNode;
            if (node != null)
            {
                MiniForms.ConnectionForm ConnForm = newConnection ? new MiniForms.ConnectionForm()
                    : new MiniForms.ConnectionForm(node, ConnectionList[node.Index]);
                ConnForm.ShowDialog(this);
            }
        }

        // add new Connection, and add it to tree view.
        public void addConnection(bool ConnectionFromFile, Connection conn)
        {
            // add to list
            ConnectionList.Add(conn);
            connectionOpened.Add(false);
            databaseOpened.Add(new List<bool>());
            //
            if (!ConnectionFromFile)
                checkConnectionName(ConnectionList.Count - 1); // last Connection (newest)
            createConnectionNode(conn);
            serverCountLabel.Text = (Int32.Parse(serverCountLabel.Text) + 1).ToString();
        }

        //check name of a Connection, if it 's same name as an other Connection, rename it.
        private void checkConnectionName(int ConnectionIndex)
        {
            int count = ConnectionList.Count;
            if (count > 1)
            {
                for (int i = 0; i < count; i++)
                {
                    if (i != ConnectionIndex && ConnectionList[ConnectionIndex].Name.Equals(ConnectionList[i].Name))
                    {
                        ConnectionList[count - 1].Name += "1";
                        checkConnectionName(ConnectionIndex);
                        break;
                    }
                }
            }
        }

        //open Connection and create database nodes
        private void openConnection(TreeNode selectedNode)
        {
            if (!connectionOpened[selectedNode.Index])
            {
                this.Cursor = Cursors.WaitCursor;
                try
                {
                    createDatabaseNodes(selectedNode);
                    connectionOpened[selectedNode.Index] = true;
                    //status Label
                    openedServerCountLabel.Text = (Int32.Parse(openedServerCountLabel.Text) + 1).ToString();
                    setDatabaseCountVisible(true);
                    dbCountLabel.Text = selectedNode.Nodes.Count.ToString();
                    setServerStatus(selectedConnection);
                    //
                    selectedNode.Expand();
                    setOpenedConnectionOptionsEnabled(true);
                    selectedNode.ImageIndex = 1;
                    selectedNode.SelectedImageIndex = 1;
                }
                catch (Exception e)
                {
                    connectionOpened[selectedNode.Index] = false;
                    MessageBox.Show(this, e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                this.Cursor = Cursors.Default;
            }
            else selectedNode.Expand();
        }

        //close
        private void closeConnection(TreeNode selectedNode)
        {
            removeComponents(selectedNode);
            ConnectionList[selectedNode.Index].closeConnection();
            connectionOpened[selectedNode.Index] = false;
            for (int i = 0; i < databaseOpened[selectedNode.Index].Count; i++)
            {
                databaseOpened[selectedNode.Index][i] = false;
            }
            setOpenedConnectionOptionsEnabled(false);
            selectedNode.ImageIndex = 0;
            selectedNode.SelectedImageIndex = 0;
            // status label
            openedServerCountLabel.Text = (Int32.Parse(openedServerCountLabel.Text) - 1).ToString();
            setDatabaseCountVisible(false);
            setServerStatus(selectedConnection);
            //
        }

        // refresh
        private void refreshConnection(TreeNode selectedNode)
        {
            closeConnection(selectedNode);
            openConnection(selectedNode);
        }

        // update properties
        public void updateConnectionProperties(TreeNode selectedNode, Connection newConnection)
        {
            int index = selectedNode.Index;
            closeConnection(selectedNode);
            ConnectionList[index] = newConnection;
            checkConnectionName(index);
            selectedNode.Text = selectedNode.Name = newConnection.Name;
        }

        // delete
        public void deleteConnection(String nodeName)
        {
            TreeNode node = treeView.Nodes[nodeName];
            serverCountLabel.Text = (Int32.Parse(serverCountLabel.Text) - 1).ToString();
            if (connectionOpened[node.Index])
            {
                openedServerCountLabel.Text = (Int32.Parse(openedServerCountLabel.Text) - 1).ToString();
            }
            removeComponents(node);
            treeView.Nodes.Remove(node);
            ConnectionList.RemoveAt(node.Index);
            connectionOpened.RemoveAt(node.Index);
            databaseOpened.RemoveAt(node.Index);
            selectedConnection = 0;
            if (treeView.Nodes.Count == 0)
            {
                setServerNameStatusVisible(false);
            }
        }
        
        // determind selected connection
        private void getSelectedConnection(String ConnName)
        {
            foreach (Connection Conn in ConnectionList)
            {
                if (Conn.Name.Equals(ConnName))
                {
                    selectedConnection = ConnectionList.IndexOf(Conn);
                    break;
                }
            }
        }

        #region save / open / delete Connections from file
        private void openConnectionFiles()
        {
            string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            if (isAppDataDirCreated(path, "Connections"))
            {
                string ConnectionsPath = Path.Combine(path, "UITDMMTools\\Connections");
                string[] fileNames = Directory.GetFiles(ConnectionsPath);
                for (int i = 0; i < fileNames.Length; i++)
                {
                    try
                    {
                        FileStream file = new FileStream(fileNames[i], FileMode.Open);
                        Connection Conn = new Connection();
                        string ConnStr = "";
                        int n;
                        while ((n = file.ReadByte()) != -1)
                        {
                            ConnStr += (char)n;
                        }
                        file.Close();
                        Conn.ConnectionString = ConnStr;
                        string[] fileName = file.Name.Split('\\');
                        Conn.Name = fileName[fileName.Length - 1];
                        addConnection(true, Conn);
                    }
                    catch (Exception) { continue; }
                }
            }
        }

        private void saveConnetion(Connection Conn, String ConnectionPath)
        {
            string fileName = Path.Combine(ConnectionPath, Conn.Name);
            FileStream file;
            try
            {
                file = new FileStream(fileName, FileMode.Open);
            }
            catch (IOException)
            {
                file = new FileStream(fileName, FileMode.Create);
            }
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] bytes = encoding.GetBytes(Conn.ConnectionString);
            file.Write(bytes, 0, bytes.Length);
            file.Close();
        }

        private void saveAllConnections()
        {
            string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            string appPath = Path.Combine(path, "UITDMMTools");
            string ConnectionPath = Path.Combine(appPath, "Connections");
            if (!isAppDataDirCreated(path))
            {
                Directory.CreateDirectory(appPath);
                Directory.CreateDirectory(ConnectionPath);
            }
            else if (!isAppDataDirCreated(path, "Connections"))
            {
                Directory.CreateDirectory(ConnectionPath);
            }
            deleteConnectionFiles(ConnectionPath);
            foreach (Connection con in ConnectionList)
            {
                saveConnetion(con, ConnectionPath);
            }
        }

        private void deleteConnectionFiles(String ConnectionPath)
        {
            foreach (String file in Directory.GetFiles(ConnectionPath))
            {
                try
                {
                    File.Delete(file);
                }
                catch (IOException){}
            }
        }

        private bool isAppDataDirCreated(string appPath)
        {
            foreach (string dir in Directory.GetDirectories(appPath))
            {
                if (dir.Equals("UITDMMTools"))
                {
                    return true;
                }
            }
            return false;
        }

        private bool isAppDataDirCreated(string appPath, string option)
        {
            string path = Path.Combine(appPath, "UITDMMTools");
            string optionPath = Path.Combine(path, option);
            foreach (string dir in Directory.GetDirectories(path))
            {
                if (dir.Equals(optionPath))
                {
                    return true;
                }
            }
            return false;
        }
        #endregion
        #endregion

        #region Database
        private void openDatabase(TreeNode node)
        {
            String[] path = node.FullPath.Split('\\');
            if (!databaseOpened[selectedConnection][node.Index])
            {
                this.Cursor = Cursors.WaitCursor;
                try
                {
                    createOptionNodes(ConnectionList[selectedConnection], path[1]);
                    node.Expand();
                    node.ImageIndex = 3;
                    node.SelectedImageIndex = 3;
                    addItemsToList(0, treeView.Nodes[path[0]].Nodes[path[1]].Nodes[0].Nodes);// table
                    databaseOpened[selectedConnection][node.Index] = true;
                    databaseSelected = new Point(selectedConnection, node.Index);
                    // options
                    setOptionSelected(0);
                    setOptionButtonsText(0, selectedOptionIndex);

                    // database status
                    setDatabaseDetailsStatusVisible(true);
                    dbNameLabel.Text = node.Text;
                    setOptionsStatus(0, node.Nodes[0].Nodes.Count);
                    //
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                this.Cursor = Cursors.Default;
            }
        }

        private void closeDatabase(TreeNode node)
        {
            removeComponents(node);
            node.ImageIndex = 2;
            node.SelectedImageIndex = 2;
            databaseOpened[selectedConnection][node.Index] = false;
            databaseSelected = new Point(-1, -1);
            setDatabaseDetailsStatusVisible(false);
            setDatabaseCountVisible(false);
            ConnectionList[selectedConnection].closeDatabase();
        }

        private void refreshDatabase(TreeNode databaseNode)
        {
            closeDatabase(databaseNode);
            openDatabase(databaseNode);
        }

        public void deleteDatabase(string key)
        {
            try
            {
                ConnectionList[selectedConnection].dropDatabase(key);
                TreeNode dbNode = treeView.Nodes[selectedConnection].Nodes[key];
                dbNode.Remove();
                databaseOpened[selectedConnection].RemoveAt(dbNode.Index);
                databaseSelected = new Point(-1, -1);
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void showDatabaseForm()
        {
            MiniForms.DatabaseForm dbForm = new MiniForms.DatabaseForm(ConnectionList[selectedConnection]);
            dbForm.ShowDialog(this);
        }

        public void createNewDatabase(Connection Conn, string dbName, string charset, string collation)
        {
            try
            {
                Conn.createDatabase(dbName, charset, collation);
                int ConnIndex = ConnectionList.IndexOf(Conn);
                if (treeView.Nodes[ConnIndex].Nodes[dbName] == null)
                {
                    treeView.Nodes[ConnIndex].Nodes.Add(dbName, dbName, 2, 1);
                    databaseOpened[ConnIndex].Add(false);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(this, e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion

        #region Tree view
        private void createConnectionNode(Connection conn)
        {
            TreeNode node = new TreeNode();
            node.Text = node.Name = conn.Name;
            node.ContextMenuStrip = connectionContextMenu;
            treeView.Nodes.Add(node);
            treeView.SelectedNode = node;
        }

        private void createDatabaseNodes(TreeNode selectedNode)
        {
            DataTable DBData = ConnectionList[selectedNode.Index].getSchemaInfo("Databases");
            foreach (DataRow row in DBData.Rows)
            {
                String DBName = row[1].ToString();
                TreeNode node = new TreeNode(DBName, 2, 2);
                node.Name = DBName;
                node.ContextMenuStrip = databaseContextMenu;
                treeView.Nodes[ConnectionList[selectedNode.Index].Name].Nodes.Add(node);
                databaseOpened[selectedNode.Index].Add(false);
            }
        }

        private void createOptionNodes(Connection conn, String database)
        {
            TreeNode node = new TreeNode("Tables", 4, 4);
            node.Name = "tables";
            node.ContextMenuStrip = tablesContextMenu;
            treeView.Nodes[conn.Name].Nodes[database].Nodes.Add(node);
            createDetailsNodes(conn, database, "tables");

            node = new TreeNode("Queries", 6, 6);
            node.Name = "queries";
            node.ContextMenuStrip = queriesContextMenu;
            treeView.Nodes[conn.Name].Nodes[database].Nodes.Add(node);
            createDetailsNodes(conn, database, "queries");

            node = new TreeNode("Views", 7, 7);
            node.Name = "views";
            node.ContextMenuStrip = viewsContextMenu;
            treeView.Nodes[conn.Name].Nodes[database].Nodes.Add(node);
            createDetailsNodes(conn, database, "views");

            node = new TreeNode("Functions", 7, 7);
            node.Name = "functions";
            node.ContextMenuStrip = functionsContextMenu;
            treeView.Nodes[conn.Name].Nodes[database].Nodes.Add(node);
            createDetailsNodes(conn, database, "functions");

            node = new TreeNode("Backups", 8, 8);
            node.Name = "backups";
            node.ContextMenuStrip = backupsContextMenu;
            treeView.Nodes[conn.Name].Nodes[database].Nodes.Add(node);
            createDetailsNodes(conn, database, "backups");
        }

        private void createDetailsNodes(Connection Conn, String database, String option)
        {
            switch (option)
            {
                case "tables":
                    treeView.Nodes[Conn.Name].Nodes[database].Nodes[option].Nodes.Clear();
                    Conn.setDatabase(database);
                    DataTable DBData = Conn.getSchemaInfo(option);
                    foreach (DataRow row in DBData.Rows)
                    {
                        String name = row[2].ToString();
                        TreeNode node = new TreeNode(name, 5, 5);
                        node.Name = name + "@" + database;
                        node.ContextMenuStrip = tableContextMenu;
                        treeView.Nodes[selectedConnection].Nodes[database].Nodes[option].Nodes.Add(node); // example: mmt05@markmanager
                    }
                    break;
                default: break;
            }
        }

        /// <summary>
        /// Add all chirdren of a tree node to list.
        /// </summary>
        /// <param name="nodes"></param>
        private void addItemsToList(int index, TreeNodeCollection nodes)
        {
            clearListViewItems();

            foreach (TreeNode optionNode in nodes)
            {
                listView1.Items.Add(optionNode.Name, optionNode.Text, index);
            }
        }

        // double click
        private void treeView1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            if (node != null)
            {
                String[] path = node.FullPath.Split('\\');
                switch (node.Level)
                {
                    case 0: // Connection
                        openConnection(node);
                        break;
                    case 1: // database
                        openDatabase(node);
                        break;
                    case 3: // child of options (tables, view ...)
                        if (node.Parent.Index == 0) // table
                        {
                            openTable(node.Name);
                        }
                        break;
                    default: break;
                }
            }
        }

        // after select
        private void treeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            TreeNode node = treeView.SelectedNode;
            getSelectedConnection(node.FullPath.Split('\\')[0]);
            switch (node.Level)
            {
                case 0: // Connection
                    setConnectionOptionsEnabled(true);
                    dataGridView1.DataSource = null;
                    setOpenedConnectionOptionsEnabled(connectionOpened[node.Index]);
                    clearListViewItems();
                    // status Label
                    setServerNameStatusVisible(true);
                    setServerStatus(selectedConnection);
                    setDatabaseCountVisible(connectionOpened[node.Index]);
                    setDatabaseDetailsStatusVisible(false);
                    //

                    break;
                case 1: // database
                    setConnectionOptionsEnabled(false);
                    usersManagerButton.Enabled = true;
                    if (databaseOpened[selectedConnection][node.Index])
                    {
                        setOptionSelected(0); // table
                        setOptionButtonsText(0, selectedOptionIndex);
                        databaseSelected = new Point(selectedConnection, node.Index);
                        ConnectionList[node.Parent.Index].setDatabase(node.Text);
                        addItemsToList(0, node.Nodes[0].Nodes); // tables
                        dataGridView1.DataSource = null;

                        // database status
                        setDatabaseDetailsStatusVisible(true);
                        dbNameLabel.Text = node.Text;
                        setOptionsStatus(0, node.Nodes[0].Nodes.Count);
                        //
                    }
                    else
                    {
                        setDatabaseDetailsStatusVisible(false);
                        clearListViewItems();
                    }
                    setServerStatus(selectedConnection);

                    break;
                case 2: // options
                    setOptionSelected(node.Index);
                    setOptionButtonsText(0, selectedOptionIndex);

                    databaseSelected = new Point(selectedConnection, node.Parent.Index);

                    setConnectionOptionsEnabled(false);
                    addItemsToList(node.Index, node.Nodes);
                    ConnectionList[node.Parent.Parent.Index].setDatabase(node.Parent.Text);
                    dataGridView1.DataSource = null;
                    usersManagerButton.Enabled = true;

                    // status label
                    setServerStatus(selectedConnection);
                    setDatabaseDetailsStatusVisible(true);
                    dbNameLabel.Text = node.Parent.Text;
                    setOptionsStatus(node.Index, node.Nodes.Count);
                    //

                    break;
                case 3: // child of options
                    setOptionSelected(node.Parent.Index);
                    setOptionButtonsText(0, selectedOptionIndex);
                    usersManagerButton.Enabled = true;
                    databaseSelected = new Point(selectedConnection, node.Parent.Parent.Index);
                    addItemsToList(node.Parent.Index, node.Parent.Nodes);
                    if (node.Parent.Index == 0) // table
                    {
                        getTableInfo(false, node.Text, node.Name.Split('@')[1]);
                    }

                    // status label
                    setServerStatus(selectedConnection);
                    setDatabaseDetailsStatusVisible(true);
                    dbNameLabel.Text = node.Parent.Parent.Text;
                    setOptionsStatus(node.Parent.Index, node.Parent.Nodes.Count);
                    //

                    break;
                default:
                    setConnectionOptionsEnabled(false);
                    break;
            }
            this.Cursor = Cursors.Default;
        }

        //mouse down
        private void treeView_MouseDown(object sender, MouseEventArgs e)
        {
            treeView.SelectedNode = treeView.GetNodeAt(e.Location);
        }

        //focus leave
        private void treeView_Leave(object sender, EventArgs e)
        {
            if (autoHide && !splitContainer1.Panel1Collapsed)
            {
                setTreeViewVisible(false);
            }
        }

        // mouse leave
        private void treeView_MouseLeave(object sender, EventArgs e)
        {
            if (autoHide)
            {
                if (isConnectionViewMouseLeft())
                    setTreeViewVisible(false);
            }
        }

        //key down ( F5 to refresh )
        private void treeView_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F5)
            {
                TreeNode node = treeView.SelectedNode;
                if (node != null)
                {
                    switch (node.Level)
                    {
                        case 0: // connection
                            if (connectionOpened[selectedConnection])
                            {
                                refreshConnection(node);
                            }
                            break;
                        case 1: // database
                            if (databaseOpened[selectedConnection][node.Index])
                            {
                                refreshDatabase(node);
                            }
                            break;
                        case 2: // options
                            refreshOptions__Click(sender, null);
                            break;
                        default: break;
                    }
                }
            }
        }

        #region Methods to set Connection treeview position
        private bool autoHide = false;

        private void showHideTreeviewButton_Click(object sender, EventArgs e)
        {
            setTreeViewVisible(splitContainer1.Panel1Collapsed);
        }

        private void setTreeViewVisible(bool b)
        {
            splitContainer1.Panel1Collapsed = !b;
            this.showHideTreeviewButton.Image = !b ? global::DatabaseAdminTools.Properties.Resources.expand_vertical
                : global::DatabaseAdminTools.Properties.Resources.collpase_vertical;
            this.showHideTreeviewButton.Cursor = !b ? Cursors.PanEast : Cursors.PanWest;
        }

        private void setTreeviewAutoHide(bool b)
        {
            autoHide = b;

            dockToolStripMenuItem.Enabled = b;
            dockToolStripMenuItem.Checked = !b;
            dockToolStripMenuItem1.Checked = !b;
            dockToolStripMenuItem1.Enabled = b;

            autoHideToolStripMenuItem.Checked = b;
            autoHideToolStripMenuItem.Enabled = !b;
            autoHideToolStripMenuItem1.Checked = b;
            autoHideToolStripMenuItem1.Enabled = !b;

            setTreeViewVisible(!b);
        }

        private void showHideTreeviewButton_MouseEnter(object sender, EventArgs e)
        {
            if (autoHide)
            {
                setTreeViewVisible(true);
            }
        }

        private bool isConnectionViewMouseLeft()
        {
            Point panel1Location = new Point(this.Location.X + splitContainer1.Location.X, this.Location.Y + splitContainer1.Location.Y);
            return (Cursor.Position.X < panel1Location.X + 10 || Cursor.Position.X > panel1Location.X + splitContainer1.Panel1.Width ||
                    Cursor.Position.Y < panel1Location.Y || Cursor.Position.Y > panel1Location.Y + splitContainer1.Panel1.Height);
        }
        #endregion

        #endregion

        private void removeComponents(TreeNode selectedNode)
        {
            selectedNode.Nodes.Clear();
            clearListViewItems();
            dataGridView1.DataSource = null;
        }

        private void showDeleteConfirm(string option, string key, string text)
        {
            ConfirmForm form = new ConfirmForm(option, key);
            form.show(this, text, "Confirm");
        }
        #endregion

        #region Table / query / view / function / backup
        /// <summary>
        /// set table / query / view or .... selected by id (0 -> 5).
        /// </summary>
        /// <param name="trueIndex">0: Table - 1: Query - 2: View - 3: Function - 4: Backup</param>
        private void setOptionSelected(int trueIndex) // table / query / view/ backup
        {
            switch (trueIndex)
            {
                case 0:
                    listView1.ContextMenuStrip = tableContextMenu;
                    break;
                default:
                    listView1.ContextMenuStrip = null;
                    break;
            }
            optionSelected[trueIndex] = true;
            for (int i = 0; i < 5; i++)
            {
                if (i != trueIndex) optionSelected[i] = false;
            }
        }

        /// <summary>
        /// Open a table in table form.
        /// </summary>
        /// <param name="name">Table name contraints database (table@database)</param>
        private void openTable(String name)
        {
            this.Cursor = Cursors.WaitCursor;
            if (TableForm.OPENED)
            {
                tableView.addTab(ConnectionList[selectedConnection], name);
                tableView.Focus();
            }
            else
            {
                tableView = new TableForm();
                tableView.Show();
                tableView.addTab(ConnectionList[selectedConnection], name);
            }
            this.Cursor = Cursors.Default;
        }

        /// <summary>
        /// Get Table Information.
        /// </summary>
        /// <param name="table">Table Name</param>
        /// <param name="database">Database Name</param>
        private void getTableInfo(bool show, string table, string database)
        {
            if (show)
            {
                setTableInfoVisible(true);
            }
            if (!splitContainer2.Panel2Collapsed)
            {
                this.Cursor = Cursors.WaitCursor;
                try
                {
                    dataGridView1.DataSource = new SqlTable(ConnectionList[selectedConnection], table, database).Info;
                    //dataGridView1.Columns[0].Width = 300;
                    foreach (DataGridViewColumn col in dataGridView1.Columns)
                    {
                        col.SortMode = DataGridViewColumnSortMode.NotSortable;
                    }
                    dataGridView1.Rows[1].Cells[1].Style.Font = new Font("Segoe UI", 11, FontStyle.Italic);
                    dataGridView1.Rows[0].Selected = false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                this.Cursor = Cursors.Default;
            }
        }


        #endregion

        #region Status Label
        /// <summary>
        /// Set visible of Database count label in status toolstrip.
        /// </summary>
        /// <param name="b">True if visible</param>
        private void setDatabaseCountVisible(bool b)
        {
            toolStripLabel5.Visible = b;
            dbCountLabel.Visible = b;
            toolStripSeparator18.Visible = b;
        }

        /// <summary>
        /// Set visible of server name label in status toolstrip.
        /// </summary>
        /// <param name="b">True if visible</param>
        private void setServerNameStatusVisible(bool b)
        {
            hostNameLabel.Visible = b;
            userNameLabel.Visible = b;
            toolStripLabel8.Visible = b;
            toolStripLabel10.Visible = b;
            toolStripSeparator20.Visible = b;
        }

        /// <summary>
        /// Set the server status in status tool strip. The text of hostNameLabel, userNameLabel and image of server Name Label will be set.
        /// </summary>
        /// <param name="conn">Index of connection will be set status</param>
        private void setServerStatus(int connectionIndex)
        {
            hostNameLabel.Text = ConnectionList[connectionIndex].Name;
            userNameLabel.Text = ConnectionList[connectionIndex].userName;
            toolStripLabel8.Image = connectionOpened[connectionIndex] ?
                global::DatabaseAdminTools.Properties.Resources.server_databse : global::DatabaseAdminTools.Properties.Resources.server_disconnect;
        }

        /// <summary>
        /// Set visible of database detail labels in status tool strip
        /// </summary>
        /// <param name="b">true if visible</param>
        private void setDatabaseDetailsStatusVisible(bool b)
        {
            toolStripLabel11.Visible = b;
            dbNameLabel.Visible = b;
            toolStripSeparator22.Visible = b;
            optionNameLabel.Visible = optionCountLabel.Visible = b;
            toolStripSeparator21.Visible = toolStripSeparator24.Visible = b;
        }

        private void setOptionsStatus(int index, int count)
        {
            optionCountLabel.Text = count.ToString();
            switch (index)
            {
                case 0: // table
                    optionNameLabel.Text = "Tables :";
                    optionNameLabel.Image = global ::DatabaseAdminTools.Properties.Resources.database_table_icon;
                    break;
                case 1: // table
                    optionNameLabel.Text = "Queries :";
                    optionNameLabel.Image = global ::DatabaseAdminTools.Properties.Resources.query;
                    break;
                case 2: // table
                    optionNameLabel.Text = "Views :";
                    optionNameLabel.Image = global ::DatabaseAdminTools.Properties.Resources.view;
                    break;
                case 3: // table
                    optionNameLabel.Text = "Functions :";
                    optionNameLabel.Image = global ::DatabaseAdminTools.Properties.Resources.database_function;
                    break;
                case 4: // table
                    optionNameLabel.Text = "Backups :";
                    optionNameLabel.Image = global ::DatabaseAdminTools.Properties.Resources.backup_database;
                    break;
            }
        }
        #endregion

        #region List view and context menu event

        // View options ///////////////////////////////////////////////////////////////////////////////
        // small view option
        private void smallToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setListView1View("small");
        }

        //large view option
        private void largToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setListView1View("large");
        }

        // list view option
        private void listToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setListView1View("list");
        }

        // tile view option
        private void tileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setListView1View("tile");
        }

        private void setListView1View(string viewOption)
        {
            viewOption = viewOption.ToLower();
            removeAllViewCheck();
            ((RadioButton)viewPanel.Controls[viewOption+"ViewRadioButton"]).Checked = true;
            ((ToolStripMenuItem)listViewToolStripMenuItem.DropDownItems[viewOption + "ViewMenuItem"]).Checked = true;
            if (viewOption.Equals("small"))
            {
                listView1.View = View.SmallIcon;
            }
            else if (viewOption.Equals("large"))
            {
                listView1.View = View.LargeIcon;
            }
            else if (viewOption.Equals("tile"))
            {
                listView1.View = View.Tile;
            }
            else
            {
                listView1.View = View.List;
            }
        }

        ///////// show / hide table information
        private void showHideTableInfoButton_Click(object sender, EventArgs e)
        {
            reverseTableInfoVisible();
        }
        /////////////////////////////////////////////////////////


        private void clearListViewItems()
        {
            listView1.Clear();
        }


        #region List view event
        // open table / query / view.. in list view
        private void listView1_DoubleClick(object sender, EventArgs e)
        {
            openSelectedTablesInList(listView1.SelectedItems);
        }

        private void openSelectedTablesInList(ListView.SelectedListViewItemCollection items)
        {
            if (items != null)
            {
                foreach (ListViewItem itm in items)
                {
                    openTable(itm.Name);
                }
            }
        }

        /// List View item selection changed
        private void listView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            var items = listView1.SelectedItems;
            setOptionButtonsText(items.Count, selectedOptionIndex);
        }
        /// List View selected index changed
        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            var items = listView1.SelectedItems;
            if (items != null && items.Count > 0)
            {
                getTableInfo(false, items[0].Text, items[0].Name.Split('@')[1]);
            }
        }
        #endregion

        // radiobutton in view panel ////////////////////////////////////////////////
        private void radioButton_View_CheckedChanged(object sender, EventArgs e)
        {
            RadioButton r = (RadioButton)sender;
            if (r.Checked)
            {
                setListView1View(r.Text);
            }
        }
        ///////////////////////////////////////////////////////////////////////////

        private void viewPanel_Leave(object sender, EventArgs e)
        {
            reverseViewPanelVisible();
        }

        private void reverseViewPanelVisible()
        {
            viewPanel.Visible = !viewPanel.Visible;
            viewButton.Image = viewPanel.Visible ? global::DatabaseAdminTools.Properties.Resources.arrow_right_1
                : global::DatabaseAdminTools.Properties.Resources.arrow_left1;
        }

        private void viewButton_Click(object sender, EventArgs e)
        {
            reverseViewPanelVisible();
        }

        #endregion

        #region Menu Strip Action

        #region File
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void newConnectionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            showConnectionForm(true);
        }
        #endregion

        #region View
        //////////// Connection ////////////////////////////////
        private void hideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setTreeViewVisible(splitContainer1.Panel1Collapsed);
        }

        private void dockToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setTreeviewAutoHide(false);
        }

        private void autoHideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setTreeviewAutoHide(true);
            setTreeViewVisible(false);
        }
        ///////////////////////////////////////////////////////

        ///// List View /////////////////////////////////////////////////
        private void removeAllViewCheck()
        {
            smallViewMenuItem.Checked = largeViewMenuItem.Checked = false;
            tileViewMenuItem.Checked = listViewMenuItem.Checked = false;
        }

        private void listView_View_MenuItem_Click(object sender, EventArgs e)
        {
            setListView1View(((ToolStripMenuItem)sender).Text.Replace("&",""));
        }

        private void tableInfoMenuItem_Click(object sender, EventArgs e)
        {
            reverseTableInfoVisible();
        }
        ////////////////////////////////////////////////////////////////////
        #endregion

        #endregion

        #region Option buttons / items action
        private void showHideToolBarButton_Click(object sender, EventArgs e)
        {
            toolStrip1.Visible = !toolStrip1.Visible;
            this.showHideToolBarButton.Image = toolStrip1.Visible ? global::DatabaseAdminTools.Properties.Resources.collpase_hor : global::DatabaseAdminTools.Properties.Resources.expand_hor;
            this.showHideToolBarButton.Cursor = toolStrip1.Visible ? Cursors.PanNorth : Cursors.PanSouth;
        }

        #region Option action ( table, query, view...) above list view

        #endregion

        #region Options in toolbar
        // new connection
        private void newConnection_Click(object sender, EventArgs e)
        {
            showConnectionForm(true);
        }

        // users manager
        private void usersManager_Click(object sender, EventArgs e)
        {
            if (connectionOpened[selectedConnection] && ConnectionList[selectedConnection].userName.ToLower().Equals("root"))
            {
                bool opened = false;
                foreach (Form f in UserManagerForm.CONNECTION_OPENED)
                {
                    if (f.Name.Equals(ConnectionList[selectedConnection].Name))
                    {
                        f.Focus();
                        opened = true;
                        break;
                    }
                }
                if (!opened)
                    new UserManagerForm(ConnectionList[selectedConnection]).Show();
            }
            else
            {
                MessageBox.Show(this, "[" + ConnectionList[selectedConnection].userName + "@" + ConnectionList[selectedConnection].Name + "] only ROOT can Manage Users !", "Eror", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void setOptionView(string option)
        {
            if (databaseSelected.Y != -1)
            {
                treeView.SelectedNode = treeView.Nodes[databaseSelected.X].Nodes[databaseSelected.Y].Nodes[option];
            }
        }

        // option view ( table / query ... ) click
        private void optionsViewButton_Click(object sender, EventArgs e)
        {
            setOptionView(((ToolStripButton)sender).Text.ToLower());
        }

        // help button
        private void helpButton_Click(object sender, EventArgs e)
        {

        }

        // about button
        private void aboutButton_Click(object sender, EventArgs e)
        {

        }
        #endregion

        #region Button strip in connection toolstrip (above tree view)
        // set connection options button enabled
        private void setConnectionOptionsEnabled(bool b)
        {
            openConnButton.Enabled = b;
            closeConnButton.Enabled = b;
            delConnButton.Enabled = b;
            ConnPropertiesButton.Enabled = b;
            usersManagerButton.Enabled = b;
        }

        private void setOpenedConnectionOptionsEnabled(bool b)
        {
            usersManagerButton.Enabled = b;
            openConnButton.Enabled = !b;
            closeConnButton.Enabled = b;
        }

        // delete connection buton
        private void deleteConnection_Click(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            if (node != null)
            {
                showDeleteConfirm("delete connection", node.Name, "Are you sure to Delete this Connection (" + node.Name + ")");
            }
        }

        // connection properties button
        private void connectionProperties_Click(object sender, EventArgs e)
        {
            showConnectionForm(false);
        }

        // open connection button
        private void openConnection_Click(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            if (node != null)
            {
                openConnection(node);
            }
        }

        // close connection
        private void closeConnection_Click(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            if (node != null)
            {
                closeConnection(node);
            }
        }

        // treePositionDropDownButton
        // hide connection treeview item click
        private void hideToolStripMenuItem2_Click(object sender, EventArgs e)
        {
            setTreeViewVisible(false);
        }

        // set connection treeview dock
        private void dockToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            setTreeviewAutoHide(false);
        }

        // set connection treeview auto hide
        private void autoHideToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            setTreeviewAutoHide(true);
        }
        //
        #endregion

        #endregion

        #region Option Buttons above list view

        private void newStripButton_Click(object sender, EventArgs e)
        {

        }

        private void openStripButton_Click(object sender, EventArgs e)
        {
            openSelectedTablesInList(listView1.SelectedItems);
        }

        private void designStripButton_Click(object sender, EventArgs e)
        {

        }

        private void deleteStripButton_Click(object sender, EventArgs e)
        {

        }

        // buttons Enabled
        private void setOptionButtonsEnabled(bool b)
        {
            openStripButton.Enabled = b;
            deleteStripButton.Enabled = b;
            designStripButton.Enabled = b;
        }

        // set Text for option buttons in toolstrip
        private void setOptionButtonsText(int countSelectedItems, int option)
        {
            bool b = countSelectedItems > 0 && option != -1;
            newStripButton.Enabled = option != -1;
            setOptionButtonsEnabled(b);
            switch (option)
            {
                case 0:// table
                    openStripButton.Text = "Open Tables";
                    designStripButton.Text = "Design Tables";
                    deleteStripButton.Text = "Delete Tables";
                    newStripButton.Text = "New Table";
                    break;
                case 1: // query
                    openStripButton.Text = "Open Queries";
                    designStripButton.Text = "Design Queries";
                    deleteStripButton.Text = "Delete Queries";
                    newStripButton.Text = "New Query";
                    break;
                case 2: // view
                    newStripButton.Text = "New View";
                    break;
                case 3: // function
                    newStripButton.Text = "New Function";
                    break;
                case 4: // backup
                    newStripButton.Text = "New Backup";
                    break;
                default: break;
            }
        }
        #endregion

        #region Context menu trip

        #region Connection context Menu
        // open database
        private void openDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            toolStripTextBox1.Text = "";
            toolStripTextBox1.Focus();
        }

        private void toolStripTextBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                foreach (TreeNode node in treeView.SelectedNode.Nodes)
                {
                    if (node.Text.Equals(toolStripTextBox1.Text))
                    {
                        treeView.SelectedNode = node;
                        openDatabase(node);
                    }
                }
                connectionContextMenu.Close();
            }
        }
        //

        // refresh
        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            refreshConnection(treeView.SelectedNode);
        }

        // context menu opening event
        private void ConnectionContextMenu_Opening(object sender, CancelEventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            if (node.Level == 0)
            {
                bool b = connectionOpened[selectedConnection];
                openConnectionToolStripMenuItem1.Text = "Open Connection (" + node.Text + ")";
                openConnectionToolStripMenuItem1.Enabled = !b;

                closeConnectionToolStripMenuItem1.Enabled = b;
                closeConnectionToolStripMenuItem1.Text = "Close Connection (" + node.Text + ")";

                manageUsersToolStripMenuItem.Enabled = b;
                newDatabaseToolStripMenuItem.Enabled = b;
                openDatabaseToolStripMenuItem.Enabled = b;
                refreshConnItem.Enabled = b;
            }
        }
        #endregion

        #region Database Context Menu
        private void newDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            showDatabaseForm();
        }

        private void openDatabaseToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            openDatabase(treeView.SelectedNode);
        }

        private void closeDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            closeDatabase(treeView.SelectedNode);
        }

        private void databaseContextMenu_Opening(object sender, CancelEventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            bool b = databaseOpened[selectedConnection][node.Index];
            openDatabaseToolStripMenuItem1.Enabled = !b;
            closeDatabaseToolStripMenuItem.Enabled = b;
            dumpSqlFileToolStripMenuItem.Enabled = b;
            executeSqlFileToolStripMenuItem.Enabled = b;
            refreshDBItem.Enabled = b;
        }

        private void refreshToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            closeDatabase(node);
            openDatabase(node);
        }

        private void deleteDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            ConfirmForm frm = new ConfirmForm("delete database", node.Name);
            frm.show(this, "Are you sure to DELETE this database: '" + node.Name + "@" + ConnectionList[selectedConnection].Name + "' ?", "Delete Database");
        }

        private void databasePropertiesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            MiniForms.DatabaseForm dbForm = new MiniForms.DatabaseForm(ConnectionList[selectedConnection], node.Name);
            dbForm.ShowDialog(this);
        }

        private void refreshOptions__Click(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            createDetailsNodes(ConnectionList[selectedConnection], node.Parent.Name, node.Name);
        }

        private void dumpSqlFileToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void executeSqlFileToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void dataTransferToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }
        #endregion

        #region Table Options Context Menu

        private void tableContextMenu_Opening(object sender, CancelEventArgs e)
        {
            if (isConnectionViewMouseLeft()) // opening at list view
            {
                if (listView1.SelectedItems.Count == 0)
                {
                    e.Cancel = true;
                }
            }
        }

        private void openTableToolStripMenuItem_Click(object sender, EventArgs e)
        {
            toolStripTextBox2.Text = "";
            toolStripTextBox2.Focus();
        }

        private void toolStripTextBox2_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                TreeNode node = treeView.SelectedNode;
                tablesContextMenu.Close();
                this.openTable(toolStripTextBox2.Text + "@" + node.Parent.Name);
            }
        }

        private void tableOptions_Click(object sender, EventArgs e)
        {
            bool tree = (tableContextMenu.SourceControl == treeView);
            TreeNode node = treeView.SelectedNode;
            var items = listView1.SelectedItems;
            Console.WriteLine(tableContextMenu.Items.IndexOf((ToolStripMenuItem)sender));
            switch (tableContextMenu.Items.IndexOf((ToolStripMenuItem)sender))
            {
                case 0: // open table
                    if (tree)
                    {
                        openTable(node.Name);
                    }
                    else
                    {
                        openSelectedTablesInList(items);
                    }
                    break;
                case 19: // table info
                    getTableInfo(true, tree ? node.Text : items[0].Text, tree ? node.Name.Split('@')[1] : items[0].Name.Split('@')[1]);
                    break;
                default: break;
            }
        }
        #endregion

        #endregion

        #region table information
        private void reverseTableInfoVisible()
        {
            setTableInfoVisible(splitContainer2.Panel2Collapsed);
        }

        private void setTableInfoVisible(bool b)
        {
            splitContainer2.Panel2Collapsed = !b;
            setTableShowHideButtonImage(b);
            tableInfoMenuItem.Checked = b;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            tableInfoShowHideContextMenu.Show(Cursor.Position);
        }

        private void setTableInfoRightPosition(bool b)
        {
            splitContainer2.Orientation = b ? Orientation.Vertical : Orientation.Horizontal;
            showHideTableInfoButton.Dock = b ? DockStyle.Right : DockStyle.Bottom;
            setTableShowHideButtonImage(true);
            rightToolStripMenuItem.Checked = b;
            rightToolStripMenuItem.Enabled = !b;
            bottomToolStripMenuItem.Checked = !b;
            bottomToolStripMenuItem.Enabled = b;
        }

        private void setTableShowHideButtonImage(bool showed)
        {
            if (showed)
            {
                showHideTableInfoButton.Image = splitContainer2.Orientation == Orientation.Vertical ?
                    global::DatabaseAdminTools.Properties.Resources.expand_vertical : global::DatabaseAdminTools.Properties.Resources.expand_hor;
                showHideTableInfoButton.Cursor = splitContainer2.Orientation == Orientation.Vertical ?
                    Cursors.PanEast : Cursors.PanSouth;
            }
            else
            {
                showHideTableInfoButton.Image = splitContainer2.Orientation == Orientation.Vertical ?
                    global::DatabaseAdminTools.Properties.Resources.collpase_vertical : global::DatabaseAdminTools.Properties.Resources.collpase_hor;
                showHideTableInfoButton.Cursor = splitContainer2.Orientation == Orientation.Vertical ?
                    Cursors.PanWest : Cursors.PanNorth;
            }
            showHideTableInfoButton.Width = 5;
        }

        private void rightToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setTableInfoRightPosition(true);
        }

        private void bottomToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setTableInfoRightPosition(false);
        }
        #endregion
    }
}
